package com.carpedil.redis.service.impl;

import com.carpedil.redis.config.RedisConfig;
import com.carpedil.redis.entity.CityEntity;
import com.carpedil.redis.mapper.CityMapper;
import com.carpedil.redis.service.CityService;
import com.carpedil.redis.util.RedisCacheUtil;
import com.carpedil.utils.StringUtil;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/** @author Administrator */
@Service
public class CityServiceImpl implements CityService {
  @Autowired CityMapper cityMapper;
  @Autowired RedisTemplate redisTemplate;
  @Autowired RedisCacheUtil redisCacheUtil;
  private static RLock rLock;

  @Override
  public List<CityEntity> findByUserNameAndDateTime(String username, String city) {
    // 创建锁
    rLock = RedisConfig.rLock();
    // 查询缓存
    // 1. 组装key
    String key = username + "_" + city;
    // 防止缓存穿透1  布隆过滤器  过滤不符合查询的条件(key)
    if (!StringUtil.bloomFilter.mightContain(key)) {
      return null;
    }
    // 2. 查询缓存
    List<CityEntity> entities = (List<CityEntity>) redisCacheUtil.get(key);
    if (null == entities || entities.isEmpty()) {
      System.out.println("查询数据库");
      // 获取锁
      try {
        boolean b =
            rLock.tryLock(StringUtil.LOCK_WAIT_TIME, StringUtil.LOCK_TIME, TimeUnit.SECONDS);
        if (b) {
          // 查询数据库
          entities = cityMapper.findByUserNameAndDateTime(username, city);
          // 放入缓存
          // 防止缓存雪崩,设置不同的缓存时间(随机)
          long time = System.currentTimeMillis() % 60;
          if (time <= 30) {
            time = 30;
          }
          if (null == entities) {
            // 防止缓存穿透2  将null存入redis,设置较短过期时间
            redisCacheUtil.set(key, null, StringUtil.CACHE_NULL);
          } else {
            redisCacheUtil.set(key, entities, time);
          }
          // 释放锁
          if (!rLock.isLocked()) {
            rLock.unlock();
          }
        } else {
          Thread.sleep(StringUtil.THREAD_SLEEP_TIME);
          System.out.println("休眠结束,查询缓存");
          this.findByUserNameAndDateTime(username, city);
        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    return entities;
  }
}
